package com.wlz.demo;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 *   zookeeper 客户端 实现 节点循环监听 功能
 *  1. 启动main 方法， 创建 、myconfig 节点，并进行监听
 *  2. 再 启动一个客户端 ， set /myconfig sadafd , 修改 数据 ，watcher 就会监听到 修改的数据， 并再次对其进行监听
 * @author wlz
 * @date 2022-06-25  7:25 下午
 */
@Slf4j
public class ZkClient {

    private static final String ZK_ADDRESS = "106.52.11.147:2181";

    private static final int SESSION_TIMEOUT = 30*1000;

    private static ZooKeeper zooKeeper;

    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception{

        zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                if (event.getType() == Event.EventType.None
                    && event.getState() == Event.KeeperState.SyncConnected) {
                    log.info("连接已经建立....");
                    countDownLatch.countDown();
                }
            }
        });
        // 因为 zk 初始化是创建了两个 线程，但是这两个线程 是 守护线程，守护线程 的意思是 当没有业务线程的时候，守护线程随之停止
        countDownLatch.await();

        // 创建节点
        String s = zooKeeper.create("/myconfig", "myconfig".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        Watcher watcher = new Watcher() {
            @SneakyThrows
            @Override
            public void process(WatchedEvent event) {
                if (event.getType() == Event.EventType.NodeDataChanged
                && event.getPath() != null && event.getPath().equals("/myconfig")) {
                    log.info(" PATH: {} 发生了数据变化", event.getPath());
                    // 循环监听 this, 代码 watcher
                    byte[] data = zooKeeper.getData("/myconfig", this, null);
                    log.info("数据发送变化： {}", new String(data));
                }
            }
        };

        byte[] data = zooKeeper.getData("/myconfig", watcher, null);

        log.info("原始数据: {}", new String(data));

        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);

    }
}
